package com.ruoyi.me.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ProcessStopException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.ExecUtil;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.SseEmitterUtils;
import com.ruoyi.common.utils.biz.CommonUtil;
import com.ruoyi.common.utils.biz.ResultSaveModule;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.me.service.SpatialIndexForecastService;
import com.ruoyi.utils.TableUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;


import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

@Service
public class SpatialIndexForecastServiceImpl implements SpatialIndexForecastService {

    @Value("${python.me.spitialIndex.iniPath}")
    private String iniPath;
    @Value("${python.me.altitude.jsonPath}")
    private String jsonPath;
    @Value("${python.me.spitialIndex.path}")
    private String spitialPath;
    @Value("${python.me.spitialIndex.name}")
    private String spitialName;
    @Override
    public AjaxResult getCalculateResult(Map<String, Object> map) throws ProcessStopException {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        //将参数进行Json文件转化生成
        String json = jsonPath+System.currentTimeMillis()+".json";
        //生成json文件
        FileUtils.createJson(json, map);
        String sseId = map.get("sseId")+"";
        //进行算法调用
        sseId+=loginUser.getUsername();
        List<String> command = new ArrayList<>();
        command.add("python");
        command.add("-u");
        command.add(spitialPath+spitialName);
        command.add(json);
        command.add(iniPath);
//        //调用python程序
        System.out.println(command.get(0)+" "+command.get(1)+" "+command.get(2)+" "+command.get(3) + " " + command.get(4));
        String results = ExecUtil.execPython(command, sseId);
        if (results.contains("###")){
            System.out.println(results);
            if ( results.split("###").length < 2){
                throw new ServiceException(results);
            }
            results = results.split("###")[1];
        }
        //获取参数中方法名
        File file = new File(results);
        if (!file.exists()){
            throw new ServiceException(results + " 结果文件不存在");
        }

        Map<String, Object> resultMap = new HashMap<>();
        String content = CommonUtil.readStrData(file, null);
        Map<String, JSONObject> contentMap = JSONUtil.toBean(content, Map.class);
        //1. indexData 直接给前端。
        JSONObject indexData = contentMap.get("indexData");
        resultMap.put("indexData",indexData);

        //2.空间环境指数误差对比结果
        JSONObject errorData = contentMap.get("errorData");
        String[] dayArr = map.get("whichDay").toString().split(",");
        List<String> dayList = IntStream.range(Integer.parseInt(dayArr[0]), (Integer.parseInt(dayArr[1]) + 1))
                .mapToObj(String::valueOf)
                .collect(Collectors.toList());
        Map<String,Object> chartMap = new ConcurrentHashMap<>();
        Object timeList = indexData.get("time");
        List<String> methodList = JSONUtil.parseArray(map.get("forsecastMethod").toString()).toList(String.class);

        dayList.stream().forEach(day -> {
            //绝对误差
            Map<String,Object> dataMap= JSONUtil.toBean(errorData.get(day).toString(),Map.class);
            Map<String,Object> chartDayMapAbs = new HashMap<>();
            chartDayMapAbs.put("time", timeList);
            methodList.forEach(method -> {
                Object data = dataMap.get(method + "#forecast#absolute_error#result");
                chartDayMapAbs.put(method, data);
            });

            //相对误差
            Map<String,Object> chartDayMapRelative = new HashMap<>();
            chartDayMapRelative.put("time", timeList);
            methodList.forEach(method -> {
                Object data = dataMap.get(method + "#forecast#relative_error#result");
                chartDayMapRelative.put(method, data);
            });

            Map<String, Object> absRelativeMap = MapUtil.builder(new HashMap<String, Object>())
                    .put("abs", chartDayMapAbs)
                    .put("relative", chartDayMapRelative)
                    .build();
            chartMap.put(day, absRelativeMap);
        });
        resultMap.put("chart", chartMap);

        //3.空间环境指数统计分析结果
        Map<String,String> errorStats = new HashMap<>();
        if (dayList.size() == 1){
            errorStats = JSONUtil.toBean(errorData.get(dayList.get(0)).toString(), Map.class);
        }else {
            errorStats = JSONUtil.toBean(errorData.get("0").toString(), Map.class);
        }
        Map<String, String> finalErrorStats = errorStats;
        List<Map<String, Object>> tableDataList = methodList.stream().map(method -> {
            return MapUtil.builder(new HashMap<String, Object>())
                    .put("method", method)
                    .put("avg_absolute", finalErrorStats.get(method + "#forecast#absolute_error#confidenceInterval"))
                    .put("avg_relative", finalErrorStats.get(method + "#forecast#relative_error#confidenceInterval"))
                    .put("root", finalErrorStats.get(method + "#forecast#root_mean_square_error#result"))
                    .put("corrCoee", finalErrorStats.get(method + "#forecast#corrCoee"))
                    .build();
        }).collect(Collectors.toList());
        resultMap.put("tableData",tableDataList);

        SseEmitterUtils.sendMessage(sseId,"100");
        SseEmitterUtils.remove(sseId);

        List<String> list = Stream.of(results).collect(Collectors.toList());
        resultMap.put("resultData", JSONUtil.toJsonStr(list));
        resultMap.put("module", ResultSaveModule.MODEL_ASSESS);
        resultMap.put("submodule", ResultSaveModule.MODEL_ASSESS_SPACE);
        return AjaxResult.success("获取成功",resultMap);
    }

    @Override
    public AjaxResult download(Map<String, Object> map) {
        //进行数据解析
        //获取时间列表
//        List<String> timeList = (List<String>) map.get("timeList");
        TableUtils.createMeSpatialWord(map,null);
        return null;
    }

    @Override
    public SseEmitter push(String id, String flag) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        return SseEmitterUtils.connect(id+loginUser.getUsername(), flag);
    }
}
